﻿package rd.hardcore.engine.save 
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.net.URLStream;
	import flash.utils.getTimer;
	import rd.hardcore.datas.Track;
	import rd.hardcore.engine.datas.DatasManager;
	import rd.hardcore.events.SaveManagerEvent;
	/**
	 * ...
	 * @author Thibault Perret
	 */
	public class SaveManager extends EventDispatcher
	{
		/* CST */
		static public const OLD_URL_PATH_MP3		:	String 	= File.applicationDirectory.resolvePath("medias/songs/").nativePath;
		static public const OLD_URL_PATH_THUMB		:	String 	= File.applicationDirectory.resolvePath("medias/thumbs/").nativePath;
				
		static public const URL_PATH_MP3			:	String 	= File.applicationStorageDirectory.resolvePath("medias/songs/").nativePath;
		static public const URL_PATH_THUMB			:	String 	= File.applicationStorageDirectory.resolvePath("medias/thumbs/").nativePath;
		
		/* VAR */
		
		private static var tracksFile			:	File 	= File.applicationStorageDirectory.resolvePath("tracks.xml");
		private static var padsFile			:	File 	= File.applicationStorageDirectory.resolvePath("pads.xml");
		
		private var _songFile:File;
		private var _thumbFile:File;
		private var _wavToEncode:File;
		private var _bmpToEncode:File;
		private var _gifToEncode:File;
		private var cpt:int = 0;
		private var droped:int = 0;
		private var keyId:int;
		private var tracks:XML;
		
		private var songName:String;
		private var thumbName:String;
		
		public var track:Track;
		private var child:XML;
		
		private var newTrack : Boolean = true;
		
		// set with *.hardcore
		private var setByHardcore : Boolean;
		static private var hardcoreLoader:URLStream;
		
		public function SaveManager( _keyId : int ) 
		{
			keyId = _keyId;
		}
		
		
		public function proceedDaSave(_track:Track, _setByHardcore : Boolean ):void
		{
			setByHardcore = _setByHardcore;
			track =  DatasManager.getTrackById(_track.keyId);
			track.cpt = 0;
			
			newTrack = (track.file == "" && track.thumb == "") ? true : false;	
			
			addEventListener(Event.COMPLETE, copyFile);
			addEventListener(IOErrorEvent.IO_ERROR, handleError);
			
			/*	ENCODING ZONE	*/
			if (_wavToEncode) {
				//_songFile = encodeMethod():File
			}else if (_bmpToEncode) {
				//_thumbFile = encodeMethod():File;
			}else if (_gifToEncode) {
				//thumbFile = encodeMethod():File;
			}else {
				copyFile(null);
			}
		}
		
		
		/*	Copy File	*/
		private function copyFile(e:Event):void
		{
			removeEventListener(Event.COMPLETE, copyFile);
			removeEventListener(IOErrorEvent.IO_ERROR, handleError);
			
			// MP3
			if (_songFile)
			{
				if (!newTrack) deleteFile(track);
				
				if (setByHardcore)
					track.file = "medias/songs/" + track.file;
				else
					track.file = "medias/songs/" + duplicateFile(_songFile);
				
			}
			
			// THUMBNAIL
			if (_thumbFile)
			{
				if (!newTrack) deleteFile(track);
				
				if(setByHardcore)
					track.thumb = "medias/thumbs/" + track.thumb;
				else
					track.thumb = "medias/thumbs/" + duplicateFile(_thumbFile, 1);
			}
			
			//if (DatasManager.checkUniqueFile( track.file, track.thumb ))	return;
			
			if (!newTrack)
				updateDatasToXML();
			else
				saveDatasToXML();
			
			updatePadsXML();
			track.updateSoRefresh();
		}
		
		/**
		 * Réécriture du fichier XML
		 */
		private function updateDatasToXML():void
		{
			trace("2: construct data updateFromXML");
			
			/**					>>--** S A V E	 T R A C K S . X M L **--<<		
			 */ 
			var tracksXML:XML = DatasManager.getTracksXML();
			
			var data : XML = <data/>;
			data.appendChild(tracksXML);
			var tracksXMLStr:String = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + data.toXMLString();
			var filestream:FileStream;
			
			if (tracksFile.exists) {
				filestream = new FileStream();
				filestream.open(tracksFile, FileMode.WRITE);
				try{
					filestream.writeUTFBytes(tracksXMLStr);
				}catch (e:Error) {
					trace("2: FAILED");
					dispatchEvent(new SaveManagerEvent(SaveManagerEvent.SAVE_PROCESS_FAILED));
					return;
				}
			}
			filestream.close();
			dispatchEvent(new SaveManagerEvent(SaveManagerEvent.SAVE_PROCESS_SUCCEED));
		}
		
		private function saveDatasToXML():void
		{
			
			trace("2: construct data saveToXML");
			/**					>>--** S A V E	 T R A C K S . X M L **--<<		
			 */ 
			var tracksXML:XML = DatasManager.getTracksXML();
			var child:XML;
			
			var data : XML = <data/>;
			data.appendChild(tracksXML);
			var filestream:FileStream;
			
			if (tracksFile.exists) {
				filestream = new FileStream();
				filestream.open(tracksFile, FileMode.WRITE);
				try{
					//writeUTF place un symbole chelou devant le flush
					filestream.writeUTFBytes(data);
				}catch (e:Error) {
					dispatchEvent(new SaveManagerEvent(SaveManagerEvent.SAVE_PROCESS_FAILED));
					return;
				}
			}
			filestream.close();
			

			/**					>>--** S A V E	 T R A C K S . X M L **--<<
			 */
			var padsXML:XML = DatasManager.getPadsXML();
			var newPos:int ;
			var newChar:int;
			for each (var position:XML in padsXML.pad) {
				if (int(position[0].@["keyId"]) == track.keyId -1)
				{
					newChar = int(position[0])+1;
					newPos = int(position[0].@["pos"])+1;
				}
			}
			child = new XML("<pad keyId=\"" + track.keyId + "\" pos=\"" + newPos + "\" hit=\"0\" ><![CDATA[" + newChar + "]]></pad>");
			padsXML.appendChild(child);
			data = <data/>;
			data.appendChild(padsXML);
			
			if (padsFile.exists)
			{
				filestream = new FileStream();
				filestream.open(padsFile, FileMode.WRITE);
				try{
					//writeUTF place un symbole chelou devant le flush
					//filestream.writeUTF(Datas.datas.toXMLString());
					filestream.writeUTFBytes(data);
				}catch (e:Error) {
					dispatchEvent(new SaveManagerEvent(SaveManagerEvent.SAVE_PROCESS_FAILED));
					return;
				}
			}
			
			dispatchEvent(new SaveManagerEvent(SaveManagerEvent.SAVE_PROCESS_SUCCEED, [newChar, newPos]));
			
		}
		
		/**
		 * Supprime le fichier avant de copier le nouveau
		 */
		private function deleteFile(file:Track ):void
		{
			/*	L O L 	*/
		}
		
		/**
		 * Copy du fichier dans le répertoire approprié
		 * @param	file
		 * @return
		 */
		private function duplicateFile(file:File, fileType:int = 0):String
		{
			var sourceFile:File = new File();
			
			sourceFile.addEventListener(Event.COMPLETE, constructXML);
			sourceFile.addEventListener(IOErrorEvent.IO_ERROR, handleError);

			sourceFile = sourceFile.resolvePath(file.nativePath);
			
			var URL_PATH : String;
			
			trace("File Type: " + fileType);
			
			if (fileType == 0)	URL_PATH = URL_PATH_MP3;
			else				URL_PATH = URL_PATH_THUMB;
			
			var destination:File = new File(URL_PATH);
			destination = destination.resolvePath(file.name);
			trace("#### " + destination.name);
			trace("#### " + destination.nativePath);
			
			try {
				sourceFile.copyTo(destination, true);
			}
			catch (error:Error)
			{
				trace("3: [ADD] Error de copy de fichier");
				return "";
			}
			
			return destination.name;
		}
		
		private function constructXML(e:Event):void 
		{
			removeEventListener(Event.COMPLETE, constructXML);
			removeEventListener(IOErrorEvent.VERIFY_ERROR, handleError);
			removeEventListener(IOErrorEvent.IO_ERROR, handleError);
			removeEventListener(IOErrorEvent.DISK_ERROR, handleError);
			
			dispatchEvent(new SaveManagerEvent(SaveManagerEvent.SAVE_PROCESS_SUCCEED));
		}
		
		private function handleError(e:IOErrorEvent):void 
		{
			removeEventListener(Event.COMPLETE, constructXML);
			removeEventListener(IOErrorEvent.VERIFY_ERROR, handleError);
			removeEventListener(IOErrorEvent.IO_ERROR, handleError);
			removeEventListener(IOErrorEvent.DISK_ERROR, handleError);
			
			dispatchEvent(new SaveManagerEvent(SaveManagerEvent.SAVE_PROCESS_FAILED));
		}
		
		
		/**
		 * Mets à jour le fichier padsXML pour la sauvegarde du nombre de hits
		 */
		public static function updatePadsXML():void
		{
			CONFIG::debug{
				var t1:int = getTimer();
			}
			var padsXML:XML = DatasManager.getPadsXML();
			
			var data : XML = <data/>;
			data.appendChild(padsXML);
			var padsXMLStr:String = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + data.toXMLString();
			var filestream:FileStream;
			
			if (padsFile.exists) {
				filestream = new FileStream();
				filestream.open(padsFile, FileMode.WRITE);
				try{
					filestream.writeUTFBytes(padsXMLStr);
				}catch (e:Error) {
					trace("2: FAILED");
					return;
				}finally {
					CONFIG::debug{
						trace("0:- updatePadsXML -> " + (getTimer() - t1 )+"ms");
					}
				}
			}
			filestream.close();
		}
		
		/**
		 * Mets à jour le fichier tracksXML pour la suppresion d'une track
		 */
		public static function updateTracksXML():void
		{
			CONFIG::debug{
				var t1:int = getTimer();
			}
			var tracksXML:XML = DatasManager.getTracksXML();
			
			var data : XML = <data/>;
			data.appendChild(tracksXML);
			var tracksXMLStr:String = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + data.toXMLString();
			var filestream:FileStream;
			
			if (tracksFile.exists) {
				filestream = new FileStream();
				filestream.open(tracksFile, FileMode.WRITE);
				try{
					filestream.writeUTFBytes(tracksXMLStr);
				}catch (e:Error) {
					trace("2: FAILED");
					return;
				}finally {
					CONFIG::debug{
						trace("0:- updatePadsXML -> " + (getTimer() - t1 )+"ms");
					}
				}
			}
			filestream.close();
		}
		
		
		public function set copySongFile(file:File):void
		{
			_songFile = file;
		}
		
		public function set copyImgFile(file:File):void
		{
			_thumbFile = file;
		}
		
		/**
		 * Prépare la conversion d'un file wave en mp3
		 * @param	file
		 */
		public function set wavToMp3Encode(file:File):void
		{
			_wavToEncode = file;
		}
		
		/**
		 * Prépare la conversion d'un file BMP en jpg
		 * @param	file
		 */
		public function set bmpToJpgEncode(file:File):void
		{
			_bmpToEncode = file;
		}
		
		/**
		 * Prépare la conversion d'un file gif en png
		 * @param	file
		 */
		public function set gifToPngEncode(file:File):void
		{
			_gifToEncode = file;
		}
		
		
		
		/**
		 * On tire la chasse
		 */
		public function flush():void
		{
			cpt = 0;
			droped = 0;
			_songFile = null;
			_thumbFile = null;
			_wavToEncode = null;
			_bmpToEncode = null;
			_gifToEncode = null;
		}
		
	}

}